package com.qf.business.coupon.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.mongodb.client.result.UpdateResult;
import com.qf.business.coupon.service.CouponService;
import com.qf.commons.web.exception.ServiceException;
import com.qf.entity.base.Codes;
import com.qf.entity.base.R;
import com.qf.entity.po.Coupon;
import com.qf.entity.po.CouponContext;
import com.qf.entity.po.CouponGet;
import com.qf.entity.vo.*;
import com.qf.remote.feign.CartServerRemote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class CouponServiceImpl implements CouponService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private CartServerRemote cartServerRemote;

    @Override
    public int insertCoupon(Coupon coupon) {
        mongoTemplate.insert(coupon);
        return 1;
    }

    @Override
    public List<Coupon> list() {
        return mongoTemplate.findAll(Coupon.class);
    }

    @Override
    public int getCoupon(CouponGetVo couponGetVo) {

        //查询优惠券
        Coupon coupon = mongoTemplate.findOne(new Query(Criteria.where("_id").is(couponGetVo.getCouponId())), Coupon.class);
        if (coupon == null) {
            throw new ServiceException(Codes.FAIL);
        }

        //判断优惠券的张数
        if(coupon.getNumber() == 0){
            //优惠券已经领取完了
            throw new ServiceException(Codes.FAIL);
        }


        if (coupon.getNumber() != -1) {
            //TODO 使用预判断库存的方式进行数量的扣减
            //扣减优惠券的数量
            UpdateResult result = mongoTemplate.update(Coupon.class)
                    .matching(new Query(new Criteria().andOperator(
                            Criteria.where("_id").is(couponGetVo.getCouponId()),
                            Criteria.where("number").ne(0)
                    )))
                    .apply(new Update().inc("number", -1))
                    .first();

            if (result.getModifiedCount() == 0) {
                //没有修改成功，说明优惠券抢完了
                throw new ServiceException(Codes.FAIL);
            }
        }

        //新增领取记录
        CouponGet couponGet = new CouponGet()
                .setCouponId(couponGetVo.getCouponId())
                .setUid(couponGetVo.getUid())
                .setBeginTime(coupon.getTtlType() == 0 ? coupon.getBeginTime() : new Date())
                .setEndTime(coupon.getTtlType() == 0 ? coupon.getEndTime() : DateUtil.offsetDay(new Date(), coupon.getDays()))
                .setLimits(coupon.getLimits())
                .setRule(coupon.getRule());
        mongoTemplate.insert(couponGet);
        return 1;
    }

    /**
     * 查询当前用户名下的优惠券，根据当前购物车列表，判断哪些优惠券可用，哪些优惠券不可用
     * @param couponUseVo
     * @return
     */
    @Override
    public Map<String, List<CouponGet>> listMyCoupons(CouponUseVo couponUseVo) {

        //创建上下文对象
        CouponContext couponContext = createCouponContext(couponUseVo);
        //可用优惠券
        List<CouponGet> canUse = new ArrayList<>();
        //不可用优惠券
        List<CouponGet> noCanUse = new ArrayList<>();

        Integer uid = couponUseVo.getUid();

        //查询当前用户名下的优惠券列表
        List<CouponGet> couponGets = mongoTemplate
                .find(new Query(Criteria.where("uid").is(uid)), CouponGet.class);

        //根据领取记录，查询优惠券记录
        for (CouponGet couponGet : couponGets) {

            //根据领取记录查询优惠券的记录
            Coupon coupon = mongoTemplate
                    .findOne(new Query(Criteria.where("_id").is(couponGet.getCouponId())), Coupon.class);
            couponGet.setCoupon(coupon);

            //判断这张优惠券能否使用
            if(couponGet.canUse((CouponContext) couponContext.clone())){
                //该优惠券不可使用
                canUse.add(couponGet);
            } else {
                //该优惠券不可用
                noCanUse.add(couponGet);
            }

            System.out.println(coupon.getCouponTitle() + "判断这张该优惠券：" + couponContext.getAllPrice());
        }

        //返回集合
        return MapUtil.builder("canUse", canUse).put("noCanUse", noCanUse).build();
    }

    /**
     * 创建一个上下文对象
     * @return
     */
    @Override
    public CouponContext createCouponContext(CouponUseVo couponUseVo){
        //根据购物车的ID 查询出购物车的详细信息 - TODO 远程调用购物车服务
        List<Integer> cids = couponUseVo.getCids();
        //远程调用购物车服务，获取购物车的消息信息
        R<List<CartInfoVo>> r = cartServerRemote.queryCartsInfoByCids(cids);
        //判断是否成功
        if (!r.getCode().equals(Codes.SUCC.getCode())) {
            throw new ServiceException(Codes.FAIL);
        }

        //购物车的消息信息
        List<CartInfoVo> cartInfos = r.getData();
        System.out.println("购物车的消息信息：" + cartInfos);

        //总价
        BigDecimal allPrice = BigDecimal.ZERO;

        //计算购物车的总价
        for (CartInfoVo cartInfo : cartInfos) {
            //计算当前商品的小计
            BigDecimal xiaoji = BigDecimal.valueOf(cartInfo.getPrice())
                    .multiply(BigDecimal.valueOf(cartInfo.getNumber()))
                    .setScale(2, RoundingMode.DOWN);

            cartInfo.setXiaoji(xiaoji.doubleValue());

            //累加小计
            allPrice = allPrice.add(xiaoji);
        }
        

        //根据购物车消息信息，构建一个上下文对象
        return new CouponContext()
                .setUid(couponUseVo.getUid())
                .setCartInfoVos(cartInfos)
                .setAllPrice(allPrice.doubleValue());
    }

    /**
     * 使用该优惠券
     * @param cartPriceJisuanVo
     * @return
     */
    @Override
    public CartPriceVo useCoupon(CartPriceJisuanVo cartPriceJisuanVo) {
        //根据优惠券领取ID 查询领取对象
        CouponGet cuponGet = mongoTemplate.findOne(new Query(Criteria.where("_id").is(cartPriceJisuanVo.getCouponGetId())),
                CouponGet.class);
        //构建上下文对象
        CouponContext couponContext = createCouponContext(new CouponUseVo()
                .setUid(1)
                .setCids(cartPriceJisuanVo.getCids()));
        //通过优惠券计算优惠券的使用结果
        Double youhuiPrice = cuponGet.jisuanRule((CouponContext) couponContext.clone());

        //返回价格对象
        CartPriceVo cartPriceVo = new CartPriceVo();
        //设置总价
        cartPriceVo.setAllPrice(couponContext.getAllPrice());
        //设置优惠了多少钱
        cartPriceVo.setYouhuiPrice(youhuiPrice);
        //设置优惠后的价格
        cartPriceVo.setShijiPrice(BigDecimal.valueOf(couponContext.getAllPrice())
                .subtract(BigDecimal.valueOf(youhuiPrice)).setScale(2, RoundingMode.DOWN)
                .doubleValue());
        return cartPriceVo;
    }
}
